#include "circular_queue.h"
#include <stdlib.h>
#include <string.h>
/**
 * @brief 初始化环形任务队列
 *
 * @param q
 */
circular_queue_error_t circular_queue_init(circular_queue_t *q, const int queue_size, const int buffer_size)
{
    if (!q) return TASK_QUEUE_INIT_ERROR;

    int max_size = DEFAULT_QUEUE_SIZE;

    if (queue_size == 0) { max_size = DEFAULT_QUEUE_SIZE; }
    else { max_size = queue_size; }

    q->queue = (data_buffer *)malloc(sizeof(data_buffer) * max_size);
    if (q->queue == NULL) { goto out; }

    if (buffer_size && buffer_size < 256 && buffer_size > -1)
    {
        for (int i = 0; i < max_size; i++)
        {
            q->queue[i].buffer = (uint8_t *)malloc(buffer_size);
            if (q->queue[i].buffer == NULL) { goto out; }
        }
    }
    else
    {
        for (int i = 0; i < max_size; i++)
        {
            q->queue[i].buffer = (uint8_t *)malloc(DEFAULT_FRAME_SIZE);
            if (q->queue[i].buffer == NULL) { goto out; }
        }
    }

    q->max_size        = max_size;
    q->max_buffer_size = buffer_size;
    q->head            = 0;
    q->tail            = 0;
    q->size            = 0;
    return TASK_QUEUE_SUCCESS;

out:
    circular_queue_destroy(q);
    return TASK_QUEUE_INIT_ERROR;
}

/**
 * @brief 添加任务数据到队列尾部
 *
 * @param q 【input】任务队列
 * @param task_data 【input】任务数据
 * @return circular_queue_error_t 错误码
 */
circular_queue_error_t circular_queue_push(circular_queue_t *q, const data_buffer *task_data)
{
    if (!q || !task_data || !task_data->buffer) { return TASK_QUEUE_NULL_POINTER; }

    if (q->size >= q->max_size) { return TASK_QUEUE_FULL; }

    if (task_data->length > q->max_buffer_size) { return TASK_QUEUE_INVALID_DATA; }

    memcpy(q->queue[q->tail].buffer, task_data->buffer, task_data->length);
    q->queue[q->tail].length = task_data->length;

    q->tail = (q->tail + 1) % q->max_size;
    q->size++;

    return TASK_QUEUE_SUCCESS;
}

/**
 * @brief 从队头获取数据
 *      此函数从任务队列q中移除并返回一个任务数据。
 * @param q 【input】任务队列
 * @param task_data 【ouput】任务数据
 * @return circular_queue_error_t 错误码
 */
circular_queue_error_t circular_queue_pop(circular_queue_t *q, data_buffer *task_data)
{
    if (!q || !task_data || !task_data->buffer) { return TASK_QUEUE_NULL_POINTER; }

    if (q->size <= 0) { return TASK_QUEUE_EMPTY; }

    memcpy(task_data->buffer, q->queue[q->head].buffer, q->queue[q->head].length);
    task_data->length = q->queue[q->head].length;

    q->head = (q->head + 1) % q->max_size;
    q->size--;

    return TASK_QUEUE_SUCCESS;
}

/**
 * @brief 获取目前队头的有效数据
 *
 * @param q 【input】任务队列
 * @param task_data 【ouput】任务数据
 * @return circular_queue_error_t 错误码
 */
circular_queue_error_t circular_queue_peek(circular_queue_t *q, data_buffer *task_data)
{
    if (!q || !task_data /* || !task_data->buffer */) { return TASK_QUEUE_NULL_POINTER; }

    if (q->size <= 0) { return TASK_QUEUE_EMPTY; }

    memcpy(task_data->buffer, q->queue[q->head].buffer, q->queue[q->head].length);
    task_data->length = q->queue[q->head].length;

    return TASK_QUEUE_SUCCESS;
}

int circular_queue_size(circular_queue_t *q)
{
    return q->size;
}

int circular_queue_remaining(circular_queue_t *q)
{
    return q->max_size - q->size;
}

circular_queue_error_t circular_queue_destroy(circular_queue_t *q)
{
    if (!q) { return TASK_QUEUE_NULL_POINTER; }

    for (int i = 0; i < q->max_size; i++)
    {
        if (q->queue[i].buffer) { free(q->queue[i].buffer); }
    }
    free(q->queue);

    return TASK_QUEUE_SUCCESS;
}
